/**
 * 异步操作
 */

// js为单线程工作模式, 如果想实现异步变成, 需要了解
//  1. 同步模式和异步模式
//  2. 事件循环与消息队列
//  3. 异步编程的几种方式
//  4. Promise异步方案、宏任务/微任务队列
//  5. Generator异步方案、Async/await语法糖

// 1. 异步代码示例
console.log('global start')
setTimeout(function timer1() {
    console.log('timer1 invoke')
}, 2000)
setTimeout(function timer2() {
    console.log("timer2 invoke")
    setTimeout(function inner() {
        console.log("inner invoke")
    })
})
console.log('global end')
// 整个代码的执行结果为：global start > global end > timer2 invoke > inner invoke > timer1 invoke
// 执行过程
//      如果碰到异步执行，分别开辟一个CallBack栈用于存放执行代码，以及一个WebApis用于存放异步任务
//      以及有一个事件循环监听EventLoop和消息队列Queue
//  开始
//  执行时，console.log('global start')被压入CallBack栈后在控制台输出后弹出栈
//  setTimeout(function timer1())同样被压入CallBack栈，这个时候因为异步执行，会将timer1放入WebApis并倒计时2s
//  setTimeout(function timer2())同样被压入CallBack栈，这个时候因为异步执行，会将timer2放入WebApis并倒计时1s
//  继续执行同步模式下的代码console.log('global end')，压入CallBack栈，控制台输出后弹出栈
//  EventLoop监听到当前CallBack栈已经没有东西可以执行，但执行任务仍未结束，这个时候找到WebApis继续执行
//  又因为timer2倒计时1s，所以先将timer2压入消息队列Queue，再将timer1压入消息队列Queue
//  继续放入CallBack栈执行，console.log("timer2 invoke")压入CallBack栈后在控制台输出后弹出栈
//  这个时候又碰到异步的inner方法，同上面的步骤将inner放入WebApis并倒计时1s且压入消息队列Queue
//  console.log("inner invoke")压入CallBack栈后在控制台输出后弹出栈
//  最后到将消息队列中timer2()方法放到CallBack栈中继续执行console.log('timer1 invoke')
//  结束

// 也就是说异步任务并不会影响同步代码的执行，虽然js是单线程工作，但是浏览器是多线程执行的



// Async await
var x = 2, y = 100000;

async function main(x, y) {
    const addRes = await x + y
    const subRes = await x - y
    const mulRes = await Math.pow(x, y)
    const divRes = await x / y
    console.log(addRes, subRes, mulRes, divRes)
}

main(x, y)
